import _ from "lodash";
import { convertToNumber, MergeType, getHbTypeByZcbfid, } from "../../../tools/Tools";
// // --------- roolup worker loader 方式 TODO 待测试
// import Worker from 'worker-loader!../../../worker/cpas-table/computed.worker.js';
// // 使用 Worker
// const myWorker = new Worker();
// // --------- roolup worker loader 方式
// @ts-ignore
// import computed from "../../../worker/cpas-table/computed.worker.js";
// let myWorker = new computed();
let myWorker = new Worker(new URL("../../../worker/cpas-table/computed.worker.js", import.meta.url));
function trim(txt) {
    var afterTrimTxt = txt.replace(/^\s*/, "").replace(/\s*$/, "");
    return afterTrimTxt;
}
export const afterDocumentKeyDownHook = function (e) {
    if (this.props.afterDocumentKeyDownHook) {
        this.props.afterDocumentKeyDownHook(e);
    }
};
export const beforeColumnSortHook = function (currentSortConfig, destinationSortConfigs) {
    const sourceData = this.hot.getSourceData();
    this.sortLastSource = sourceData;
    this.hyper.setSheetContent(0, sourceData);
    // console.log("排序前恢复源数据.");
    // console.log(hyper.current.getAllSheetsSerialized());
    return true;
};
// 单元格的内容发生改变时触发（包含自己手工输入后失去焦点 + 粘贴）
export const afterChange = function (changes) {
    console.log("afterChange执行");
    const keywordsColumnIndex = 0;
    const mapsChanged = [];
    let isChanged = false;
    let changeValues = [];
    changes?.forEach(([row, col, oldValue, newValue], index) => {
        if (oldValue !== newValue) {
            // 解决合并项目列 直接删单元格数据不更新主键问题 所以去掉条件  && newValue !== "" && newValue !== null
            isChanged = true;
            changeValues.push({
                oldValue,
                newValue,
            });
        }
        const changedCellMeta = this.hot.getCellMeta(row, col);
        if (changedCellMeta.keyword) {
            // 如果是合并项目列才拼接
            // 遍历改变的每个元素 例如改了4个元素 就执行4次循环体
            const tableColumnCount = this.hot.countCols();
            if (col === keywordsColumnIndex)
                return; // 如果改的就是主键列 不做任何处理
            const keywordsColumnContent = this.hot.getDataAtCell(row, 0); // 获取改变的单元格对应的主键内容
            let primaryContentAfter = "";
            let compareContent = "";
            // 把和改变的元素同行的列都取出来拼接
            for (let i = 0; i < tableColumnCount - 1; i++) {
                if (i != keywordsColumnIndex) {
                    const perCellContent = this.hot.getDataAtCell(row, i);
                    const cellMeta = this.hot.getCellMeta(row, i);
                    if (cellMeta.type === "text" &&
                        cellMeta.keyword // 必须是合并项目列且列类型为文本才拼接
                    ) {
                        if (perCellContent === "" || perCellContent === null) {
                        }
                        else {
                            primaryContentAfter = primaryContentAfter + perCellContent + "-";
                        }
                        if (i === col) {
                            // 如果是正在修改的单元格，把修改前的值拼起来，以便和主键比对
                            if (oldValue != null && oldValue != "")
                                compareContent = compareContent + oldValue + "-";
                        }
                        else {
                            if (perCellContent != null && perCellContent != "")
                                compareContent = compareContent + perCellContent + "-";
                        }
                    }
                }
            }
            // 未修改时的拼接内容
            const oldJointContent = compareContent.substring(0, compareContent.length - 1);
            //this.hot.setDataAtCell(row, keywordsColumnIndex, primaryContentAfter)
            const deleteLastHorizontalLinePrimaryContent = primaryContentAfter.substring(0, primaryContentAfter.length - 1);
            if (keywordsColumnContent != oldJointContent && // 用户手工修改主键后 不再拼接
                keywordsColumnContent != null)
                return;
            mapsChanged.push([
                row,
                keywordsColumnIndex,
                deleteLastHorizontalLinePrimaryContent,
            ]);
        }
    });
    if (mapsChanged.length > 0) {
        this.hot.setDataAtRowProp(mapsChanged);
    }
    if (this.hot && isChanged) {
        this.setTableContentChange(true, {
            type: "检测到值变化",
            params: [...changeValues],
        });
        console.log("检测到值更新变动，更新this.data");
        this.data = this.hot.getSourceData();
    }
};
//上一次 的定时器 返回的ID
let lastTapDiffTime = 0;
//上一次 的定时器 返回的ID
let lastTapTimeFunc;
let diffParams = 300;
// 点选单元格的时候执行
export const afterOnCellMouseDownHook = function (event, coords, TD) {
    //点击时时间戳
    let curT = new Date().getTime();
    //上一次时间戳
    let lastT = lastTapDiffTime;
    //对上一次时间戳重新赋值
    lastTapDiffTime = curT;
    //做差
    let diff = curT - lastT;
    //规定300ms内点击两下判断为双击
    if (diff < diffParams) {
        //双击逻辑
        readModelDbClick.call(this, event, coords, TD);
        clearTimeout(lastTapTimeFunc);
    }
    else {
        //定时器id
        lastTapTimeFunc = setTimeout(() => {
            //单击逻辑，暂时不处理
        }, diffParams);
    }
    cellClick.call(this, event, coords, TD);
    console.log("coords", coords);
    console.log("TD", TD);
};
/**
 * 单元格双击事件
 */
const readModelDbClick = function (event, coords, TD) {
    if (this.props.dbCellClick) {
        const rmaps = this.gridService.getAllRowsMaps();
        const cmaps = this.headerService.getAllHeaderMap();
        const { row, col } = coords;
        this.props.dbCellClick(event, coords, TD, {
            rowMap: rmaps[row - 1],
            columnMap: cmaps[col - 1],
        }, this.props.name);
    }
};
/**
 * 单元格单击事件
 * @param event
 * @param coords
 * @param TD
 */
const cellClick = function (event, coords, TD) {
    //@cpastable工具栏添加隐藏遮罩
    if (coords.col > -1) {
        const columnData = this.headerService.headerColumn[coords.col];
        const isRuntime = columnData ? columnData?.config?.isRuntime : false;
        const menuToolRef = this.menuToolRef && this.menuToolRef.current
            ? this.menuToolRef.current
            : null;
        if (menuToolRef) {
            if (isRuntime) {
                menuToolRef.setMask("block");
            }
            else {
                menuToolRef.setMask("none");
            }
        }
    }
    if (coords.row > -1 && coords.col > -1) {
        console.log(this.hot.getCellMeta(coords.row, coords.col));
    }
    if (this.props.afterOnCellMouseDown) {
        this.props.afterOnCellMouseDown(event, coords, TD);
    }
};
export const updateToolBarState = function (coords, key, context) {
    if (context.menuToolRef.current) {
        context.menuToolRef.current.setToolBarState(coords);
    }
    // 设置单元格的状态回显
    updateToolBarState_Worker(context, coords);
};
//加入状态回显防抖函数
const debounceUpdateState = _.debounce(updateToolBarState, 500);
//worker 统计计算
function statisticsByRange_Worker(context) {
    const headerColumn = context.headerService.headerColumn;
    const rangeData = context.gridService.getDataByRange(context.hot.getSelectedRange());
    let worker_info = {
        funName: "statisticsByRange",
        params: {
            headerColumn,
            rangeData,
        },
    };
    myWorker.postMessage(worker_info); // 发送
    myWorker.onmessage = (event) => {
        const { code, data } = event.data;
        if (code === 200) {
            context.statisticsByRange(data);
        }
    };
}
//worker更新update状态
function updateToolBarState_Worker(context, coords) {
    console.log(updateToolBarState_Worker, "updateToolBarState_Worker---");
    const computedLevelData = context.headerService.headerLevelData.computerLevelData;
    let worker_info = {
        funName: "getToolBarStateData",
        params: {
            computedLevelData,
            coords,
        },
    };
    myWorker.postMessage(worker_info); // 发送
    myWorker.onmessage = (event) => {
        const { code, data } = event.data;
        if (code === 200) {
            const { userClickedHeaderMeta } = data;
            if (userClickedHeaderMeta && userClickedHeaderMeta.label !== "null") {
                if (context.menuToolRef.current) {
                    if (userClickedHeaderMeta.config?.ht) {
                        context.menuToolRef.current.setHeaderState(userClickedHeaderMeta?.config?.ht);
                    }
                    if (userClickedHeaderMeta.config?.bl) {
                        context.menuToolRef.current.setHeaderBlState(userClickedHeaderMeta?.config?.bl);
                    }
                    //@todo兼容cpastable的老数据
                    if (!userClickedHeaderMeta.config?.bl) {
                        context.menuToolRef.current.setHeaderBlState(1);
                    }
                    context.menuToolRef.current.setHeaderPercentFormatState(!!userClickedHeaderMeta.config?.isPercentFormat);
                    // 更新列的状态回显，只有在表头点击时才更新 row === -1的时候
                    context.menuToolRef.current?.updateColumnState(coords, userClickedHeaderMeta);
                }
                // 更新期间类型
                // 读选中列的期间类型
                const col = coords.col; // 获取用户点击的当前列
                const headerData = context.headerService.headerColumn;
                const qiJianType = headerData[col]?.config?.timeColumn?.type;
                if (qiJianType) {
                    context.menuToolRef?.current?.setQiJianType(qiJianType);
                }
                else {
                    context.menuToolRef?.current?.setQiJianType("none");
                }
            }
        }
    };
}
export const afterSelectionEndHook = function (row, column, row2, column2, selectionLayerLevel) {
    const range = this.hot.getSelectedRange();
    const range2 = range[0].getTopLeftCorner();
    //更新统计信息
    // this.statisticsByRange();
    statisticsByRange_Worker(this);
    console.log(range, "range1111");
    console.log(range[0].getTopLeftCorner(), "selectedRange.getTopLeftCorner()");
    this.setState({
        currentRange: range,
        topLeftRange: range2,
    });
    const coords = { row: row, col: column };
    const TD = this.hot.getCell(row, column);
    let key;
    if (TD) {
        key = TD.getAttribute("key");
        debounceUpdateState(coords, key, this);
    }
    this.setState({
        currentRecord: {
            coords,
            key,
        },
    });
    if (this.props.afterSelectionEndHook) {
        this.props.afterSelectionEndHook(row, column, row2, column2, selectionLayerLevel);
    }
};
export const afterColumnResizeHook = function (newSize, column, isDoubleClick) {
    // console.log("newSize");
    // console.log(newSize);
    // console.log(column);
    // this.manualColumnResize.clearManualSize(column);
    // this.manualColumnResize.setManualSize(column, newSize);
    // debugger;
    const headerColumn = this.headerService.getHeaderColumn(this.headerService.headJson);
    const mergeType = getHbTypeByZcbfid();
    //合并系统header有tzGroup的概念，需要处理
    if (mergeType !== MergeType.UNKNOW) {
        const tzGroupRes = headerColumn.filter((item, index) => index === column);
        const tzGroup = tzGroupRes && tzGroupRes.length
            ? tzGroupRes[0]?.config?.tzGroup
            : undefined;
        if (typeof tzGroup !== "undefined") {
            const res = headerColumn.filter((item, index) => {
                item.columnIndex = index;
                return item?.config?.tzGroup === tzGroup;
            });
            if (res && res.length) {
                let lastUpdateHeader = this.headJson;
                for (let i = 0; i < res.length; i++) {
                    lastUpdateHeader = this.headerService.updateHeaderConfigByIndex(lastUpdateHeader, res[i].columnIndex, {
                        width: newSize,
                    });
                }
                this.headerService.headerCompute(lastUpdateHeader);
            }
        }
    }
    else {
        const update_config_headerJson = this.headerService.updateHeaderConfigByIndex(this.headerService.headJson, column, { width: newSize });
        this.headerService.headerCompute(update_config_headerJson, false, false);
    }
    if (this.props.type && this.props.type === "zl") {
        this.containerRef.current.style.width = "90%";
    }
};
export const cellsHook = function (row, col, prop) {
    //运算规则
    // cell > row > column
    // e.g.   column width = 150     row with = 200   cell with = 300
    // e.g.   其余属性进行合并
    //配置存储
    //1. column 配置信息存储在 headerJson 信息中
    //2. row 存在于每个行的最后一列作为隐藏列  tableData
    //3. 单元格配置信息,存储在 cellMetaData 数组对象中
    // let matchCellMeta;
    let preventStyleLoss;
    if (sessionStorage.preventStyleLoss) {
        preventStyleLoss = JSON.parse(sessionStorage.preventStyleLoss);
    }
    let userAction = localStorage.userAction;
    const { action, index, amount } = this.actionType; //如果是增加行增加列需要对配置文件进行位置计算
    let matchCellMeta;
    //只有第一次加载的时候回读取 cellMeta的配置。 后续对于cell的这是都通过setCellMeta 自己来维护。否则插行插列逻辑别的很复杂(需要自己手动维护cellMetaData索引号)。
    // //每次在保存数据的时候进行一次 cellMeta保存
    if (action === "load") {
        matchCellMeta =
            this.gridService.getCellMateDataByRowAndProp(row, col, this.cellMetaData) || {};
    }
    // else {
    //   matchCellMeta = {};
    //   // 解决用户点击导入json文件 导入的是拆表后的json数据 样式不显示的问题  渲染完毕以后移除
    //   if (preventStyleLoss) {
    //     // 之前 userAction === "clickedImport" && importDismantledTableJson, 但是修改为真实隐藏列时 直接拆表也不显示样式了，所以要放大条件范围为拆表模式
    //     matchCellMeta =
    //       this.gridService.getCellMateDataByRowAndProp(
    //         row,
    //         col,
    //         this.cellMetaData
    //       ) || {};
    //   }
    // }
    const matchColumnMeta = this.gridService.getColumnMetaDataByColumn(row, col) || {};
    matchColumnMeta.dataType =
        matchColumnMeta.type === "text" ? "text" : "number";
    if (matchColumnMeta.type === "text") {
        matchColumnMeta.validator = "text";
    }
    if (matchColumnMeta.type === "numeric") {
        matchColumnMeta.validator = "numeric";
    }
    //过滤掉表头的ht,避免污染表体的ht逻辑
    if (matchColumnMeta.custom) {
        delete matchColumnMeta.custom.ht;
    }
    const matchRowMeta = this.gridService.getRowMeteDataByRow(row, this.data) || {};
    // console.log(matchColumnMeta);
    // console.log("cellsMeta 重置");
    /**
     * TODO 目前采用一种补丁的方式解决当行，列都无法决定一个单元格特性时，采用固定行号和指定属性来配置
     * 例如：0行的单元格中，有的需要校验。有的不需要校验。正常此功能应该依赖cellMetaData的单元格权重来解决
     * 但是由于为了减少复杂性和根据业务需求，这种情况比较少。所以 cellMetaData 仅在首次加载时生效。否则插行插列需要自己维护
     * 行列索引。后期自己处理行列索引根据cellMetaData
     */
    if (row === 0) {
        matchCellMeta = {
            strict: matchColumnMeta["strict"] === undefined
                ? false
                : matchColumnMeta["strict"],
        };
        //如果是默认0行配置行, 删除默认的数字CpasFormula验证器，走autotemplate默认的
        delete matchColumnMeta.validator;
    }
    /**
     * 映射行，映射列的交界处单元格属性
     */
    if (col === 0 && row === 0) {
        matchCellMeta.type = "text";
        matchCellMeta.readOnly = true;
        matchCellMeta.strict = false;
    }
    //动态行列不允许编辑, 下面注释的这种是母行可编辑，根据bug编号 CPAS6ZT-2761 修改母行不可编辑
    const isColumnDynamic = (matchColumnMeta.isDynamic || matchColumnMeta.formula) &&
        matchRowMeta.matchDynamic &&
        this.props.type !== "zl";
    const isRowDynamic = (matchRowMeta.isDynamic || matchRowMeta.formula) &&
        matchColumnMeta.matchDynamic &&
        this.props.type !== "zl";
    if (isRowDynamic || isColumnDynamic) {
        if (matchCellMeta) {
            matchCellMeta.readOnly = true;
        }
    }
    // if (row === 1 && col === 5) {
    //   matchColumnMeta.mark = Math.random();
    // }
    return {
        ...matchColumnMeta,
        ...matchRowMeta,
        ...matchCellMeta, //单元格只存储 行列不存储的内容.  例如缩进 。 宽度还是以列配置为准
    };
};
export const afterColumnSortHook = function (afterColumnSort, destinationSortConfigs) {
    console.log("排序完成");
    console.log(afterColumnSort);
    console.log(destinationSortConfigs);
    const reOrder = Array.from(
    // @ts-ignore
    this.hot.rowIndexMapper.fromPhysicalToVisualIndexesCache.keys());
    console.log(reOrder);
    const sheetId = this.hyper.getSheetId("main");
    let moved = [];
    for (let i = 0; i < reOrder.length; i++) {
        let startIndex = reOrder[i];
        const reOrderIndex = reOrder[i];
        for (let j = 0; j < moved.length; j++) {
            const moveItem = moved[j];
            if (moveItem > reOrderIndex) {
                startIndex = startIndex + 1;
            }
        }
        if (i !== startIndex) {
            console.log(`${startIndex} -> ${i}`);
            this.hyper.moveRows(sheetId, startIndex, 1, i);
            moved.push(reOrder[i]);
        }
    }
    console.log(this.hyper.getAllSheetsSerialized());
    //TODO 下方这两个会导致样式丢失，等处理排序时要把这两个解开，否则排序功能失效。 考虑是否before前移
    this.hot.loadData(this.hyper.getAllSheetsSerialized()["main"]);
    this.hot.render();
};
export const compareFunctionFactoryHook = function (sortOrder, columnMeta) {
    console.log("sortOrder", "columnMeta");
    console.log(sortOrder);
    console.log(columnMeta);
    //返回闭包函数的情况
    let _this = this;
    return function comparator(value, nextValue) {
        // Some value comparisons which will return -1, 0 or 1...
        const valueRow = value[0];
        const val = value[1];
        const nextValueRow = nextValue[0];
        const nextVal = nextValue[1];
        // 分组排序逻辑
        if (_this.tableConfig.isGroup) {
            const config = _this.gridService.getRowMeteDataByRow(valueRow);
            const groupIndex = config.groupIndex;
            const isHeaderGroup = config.groupHeader;
            const nextGroup = _this.gridService.getRowMeteDataByRow(nextValueRow);
            const nextGroupIndex = nextGroup.groupIndex;
            const nextIsHeaderGroup = nextGroup.groupHeader;
            if (sortOrder === "asc") {
                if (groupIndex !== nextGroupIndex) {
                    return groupIndex - nextGroupIndex;
                }
                else {
                    //如果是组头则不动
                    if (isHeaderGroup || nextIsHeaderGroup) {
                        return 0;
                    }
                    return val - nextVal;
                }
            }
            else if (sortOrder === "desc") {
                if (groupIndex !== nextGroupIndex) {
                    return groupIndex - nextGroupIndex;
                }
                else {
                    if (isHeaderGroup || nextIsHeaderGroup) {
                        return 0;
                    }
                    return nextVal - val;
                }
            }
        }
        else {
            if (sortOrder === "asc") {
                return val - nextVal;
            }
            else {
                return nextVal - val;
            }
        }
    };
};
function trimPasteContent(data) {
    for (let i = 0, length = data.length; i < length; i++) {
        for (let j = 0, length2 = data[i].length; j < length2; j++) {
            data[i][j] = convertToNumber(trim(data[i][j]));
        }
    }
}
export const beforePasteHook = function (data, coords) {
    console.log("beforePasteHook");
    trimPasteContent(data); // 对粘贴的内容去空格
    const { startRow, startCol, endRow, endCol } = coords[0];
    const totalDataCount = this.hot.getData().length - 1;
    const leftRowCount = totalDataCount - startRow + 1; // 剩下的行数  2
    const newDataLength = data.length;
    /**
     * 格式化货币符号
     */
    // for (let i = 0; i < data.length; i++) {
    //   const row = data[i];
    //   for (let j = 0; j < row.length; j++) {
    //     const value = row[j];
    //     data[i][j] = convertToNumber(value);
    //   }
    // }
    if (newDataLength > leftRowCount) {
        const insertCount = newDataLength - leftRowCount;
        this.gridService.addRow("bottom", true, endRow + 1, this.state.currentGroupKeyColumn, insertCount, true);
    }
};
